﻿using System;
using System.Runtime.Serialization;
using Microsoft.Xna.Framework;


namespace DKE_Kinect.Entwicklung.Kinect
{
    /// <summary>
    /// Status der Kinect Eingabe
    /// </summary>
[Serializable()]
   public class KinectState:ISerializable
   {

        #region Fields

        /// <summary>
        /// Vector der die Pos der linken Hand angibt
        /// </summary>
        private Vector3 pLeftHandPos;

        /// <summary>
        /// Vektor der die Position der rechten Hand angibt
        /// </summary>
        /// 
        private Vector3 pRightHandPos;

        /// <summary>
        /// 0 Right Arm Out
        /// </summary>
        private Boolean pRightArmOut=false;
        /// <summary>
        /// 1 Right Arm Across
        /// </summary>
        private Boolean pRightArmAcross=false;
        /// <summary>
        /// 2 Right Arm Forward
        /// </summary>
        private Boolean pRightArmForward=false;
        /// <summary>
        /// 3 Right Arm Up
        /// </summary>
        private Boolean pRightArmUp=false;
        /// <summary>
        /// 4 Right Hand Up
        /// </summary>
        private Boolean pRightHandUp=false;
        /// <summary>
        /// 5 Left Arm Out
        /// </summary>
        private Boolean pLeftArmOut=false;
        /// <summary>
        /// 6 Left Arm Across
        /// </summary>
        private Boolean pLeftArmAcross=false;
        /// <summary>
        /// 7 Left Arm Forward
        /// </summary>
        private Boolean pLeftArmForward=false;
        /// <summary>
        /// 8 Left Arm Up
        /// </summary>
        private Boolean pLeftArmUp=false;
        /// <summary>
        /// 9 Left Hand Up
        /// </summary>
        private Boolean pLeftHandUp=false;
        /// <summary>
        /// 10 Swipe Left
        /// </summary>
        private Boolean pSwipeLeft=false;
        /// <summary>
        /// 11 Swipe Right
        /// </summary>
        private Boolean pSwipeRight=false;
        /// <summary>
        /// 12 Swipe Up
        /// </summary>
        private Boolean pSwipeUp=false;
        /// <summary>
        /// 13 Swipe Down
        /// </summary>
        private Boolean pSwipeDown=false;
        /// <summary>
        /// 14 Swipe Upper Left
        /// </summary>
        private Boolean pSwipeUpperLeft=false;
        /// <summary>
        /// 15 Swipe Upper Right
        /// </summary>
        private Boolean pSwipeUpperRight=false;
        /// <summary>
        /// 16 Swipe Lower Left
        /// </summary>
        private Boolean pSwipeLowerLeft=false;
        /// <summary>
        /// 17 Swipe Lower Right
        /// </summary>
        private Boolean pSwipeLowerRight=false;

       #endregion

        #region Properties

        /// <summary>
        /// Gets or sets a value indicating whether [right arm out].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [right arm out]; otherwise, <c>false</c>.
        /// </value>
        public Boolean RightArmOut
        {
            get { return this.pRightArmOut; }
            set { this.pRightArmOut = value; }
        }

        /// <summary>
        /// Gets or sets a value indicating whether [right arm across].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [right arm across]; otherwise, <c>false</c>.
        /// </value>
        public Boolean RightArmAcross
        {
            get { return this.pRightArmAcross; }
            set { this.pRightArmAcross = value; }
        }

        
        /// <summary>
        /// Gets or sets a value indicating whether [right arm forward].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [right arm forward]; otherwise, <c>false</c>.
        /// </value>
        /// 2 Right Arm Forward
        public Boolean RightArmForward
        {
            get { return this.pRightArmForward; }
            set { this.pRightArmForward = value; }
        }
        /// <summary>
        /// Gets or sets a value indicating whether [right arm up].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [right arm up]; otherwise, <c>false</c>.
        /// </value>
        /// 3 Right Arm Up
        public Boolean RightArmUp
        {
            get { return this.pRightArmUp; }
            set { this.pRightArmUp = value; }
        }
        /// <summary>
        /// Gets or sets a value indicating whether [right hand up].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [right hand up]; otherwise, <c>false</c>.
        /// </value>
        /// 4 Right Hand Up
        public Boolean RightHandUp
        {
            get { return this.pRightHandUp; }
            set { this.pRightHandUp = value; }
        }
        /// <summary>
        /// Gets or sets a value indicating whether [left arm out].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [left arm out]; otherwise, <c>false</c>.
        /// </value>
        /// 5 Left Arm Out
        public Boolean LeftArmOut
        {
            get { return this.pLeftArmOut; }
            set { this.pLeftArmOut = value; }
        }
        /// <summary>
        /// Gets or sets a value indicating whether [left arm across].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [left arm across]; otherwise, <c>false</c>.
        /// </value>
        /// 6 Left Arm Across
        public Boolean LeftArmAcross
        {
            get { return this.pLeftArmAcross; }
            set { this.pLeftArmAcross = value; }
        }
        /// <summary>
        /// Gets or sets a value indicating whether [left arm forward].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [left arm forward]; otherwise, <c>false</c>.
        /// </value>
        /// 7 Left Arm Forward
        public Boolean LeftArmForward
        {
            get { return this.pLeftArmForward; }
            set { this.pLeftArmForward = value; }
        }
        /// <summary>
        /// Gets or sets a value indicating whether [left arm up].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [left arm up]; otherwise, <c>false</c>.
        /// </value>
        /// 8 Left Arm Up
        public Boolean LeftArmUp
        {
            get { return this.pLeftArmUp; }
            set { this.pLeftArmUp = value; }
        }
        /// <summary>
        /// Gets or sets a value indicating whether [left hand up].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [left hand up]; otherwise, <c>false</c>.
        /// </value>
        /// 9 Left Hand Up
        public Boolean LeftHandUp
        {
            get { return this.pLeftHandUp; }
            set { this.pLeftHandUp = value; }
        }
        /// <summary>
        /// Gets or sets a value indicating whether [swipe left].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [swipe left]; otherwise, <c>false</c>.
        /// </value>
        /// 10 Swipe Left
        public Boolean SwipeLeft
        {
            get { return this.pSwipeLeft; }
            set { this.pSwipeLeft = value; }
        }
        /// <summary>
        /// Gets or sets a value indicating whether [swipe right].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [swipe right]; otherwise, <c>false</c>.
        /// </value>
        /// 11 Swipe Right
        public Boolean SwipeRight
        {
            get { return this.pSwipeRight; }
            set { this.pSwipeRight = value; }
        }
        /// <summary>
        /// Gets or sets a value indicating whether [swipe up].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [swipe up]; otherwise, <c>false</c>.
        /// </value>
        /// 12 Swipe Up
        public Boolean SwipeUp
        {
            get { return this.pSwipeUp; }
            set { this.pSwipeUp = value; }
        }
        /// <summary>
        /// Gets or sets a value indicating whether [swipe down].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [swipe up]; otherwise, <c>false</c>.
        /// </value>
        /// 13 Swipe Down
        public Boolean SwipeDown
        {
            get { return this.pSwipeDown; }
            set { this.pSwipeDown = value; }
        }
        /// <summary>
        /// Gets or sets a value indicating whether [swipe upper left].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [swipe upper left]; otherwise, <c>false</c>.
        /// </value>
        /// 14 Swipe Upper Left
        public Boolean SwipeUpperLeft
        {
            get { return this.pSwipeUpperLeft; }
            set { this.pSwipeUpperLeft = value; }
        }
        /// <summary>
        /// Gets or sets a value indicating whether [swipe upper right].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [swipe upper right]; otherwise, <c>false</c>.
        /// </value>
        /// 15 Swipe Upper Right
        public Boolean SwipeUpperRight
        {
            get { return this.pSwipeUpperRight; }
            set { this.pSwipeUpperRight = value; }
        }
        /// <summary>
        /// Gets or sets a value indicating whether [swipe lower left].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [swipe lower left]; otherwise, <c>false</c>.
        /// </value>
        /// 14 Swipe Lower Left
        public Boolean SwipeLowerLeft
        {
            get { return this.pSwipeLowerLeft; }
            set { this.pSwipeLowerLeft = value; }
        }
        /// <summary>
        /// Gets or sets a value indicating whether [swipe lower right].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [swipe lower right]; otherwise, <c>false</c>.
        /// </value>
        /// 15 Swipe Lower Right
        public Boolean SwipeLowerRight
        {
            get { return this.pSwipeLowerRight; }
            set { this.pSwipeLowerRight = value; }
        }
      
        /// <summary>
        /// Getter/Setter der linken Hand
        /// </summary>
        public Vector3 LeftHand
        {
            get { return pLeftHandPos; }
            set { pLeftHandPos = value; }
        }
        /// <summary>
        /// Getter/Setter der rechten Hand
        /// </summary>
        public Vector3 RightHand
        {
            get { return pRightHandPos; }
            set { pRightHandPos = value; }
        }

        #endregion

        #region Constructors

        /// <summary>
        /// Konstruktor der einen neuen Kinect State erstellt
        /// </summary>
        public KinectState()
        {
            pLeftHandPos = Vector3.Zero;
            pRightHandPos = Vector3.Zero;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="KinectState"/> class.
        /// </summary>
        /// <param name="_state">KinectState der geklont werden soll</param>
        public KinectState(KinectState _state)
        {
            pLeftHandPos = _state.LeftHand;
            pRightHandPos = _state.RightHand;
            for (int i = 0; i < 16; i++)
            {
                SetGesture(i, _state.GetGesture(i));
            }  

        }

       /// <summary>
       /// Konstruiert einen Kinect State aus einem Record
       /// </summary>
       /// <param name="info">Gestreamtes Byteset</param>
       /// <param name="context">Stream</param>
        public KinectState(SerializationInfo info,StreamingContext context)
        {
            pLeftHandPos = (Vector3)info.GetValue("LHP", typeof(Vector3));
            pRightHandPos = (Vector3)info.GetValue("RHP", typeof(Vector3));
            for (int i = 0; i < 16; i++)
            {
                SetGesture(i, (Boolean)info.GetValue("GES"+i, typeof(Boolean)));
            }  
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="KinectState"/> class.
        /// <param name="_Gestures">Gesten-Array</param>
        /// <param name="_LeftHand">Linke-Hand-Koordinaten</param>
        /// <param name="_RightHand">Rechte-Hand-Koordinaten</param>
        /// </summary>
        public KinectState(Boolean[] _Gestures, Vector3 _LeftHand, Vector3 _RightHand)
        {
            pLeftHandPos = _LeftHand;
            pRightHandPos = _RightHand;
            if (_Gestures != null)
            {
                for (int i = 0; i < 16; i++)
                {
                    SetGesture(i, _Gestures[i]);
                }
            }
        }

        #endregion

        #region Methods

        ///TODO
        ///Daten im Kinect State updaten. Vektoren einfach überschreiben und wenn einen Geste erstellt wurde diese in "Gestures" einfügen und Funktion erstellen die pGestures an der Position 
        /// (int)Geste um 1 steigert
       
       public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("LHP", pLeftHandPos);
            info.AddValue("RHP", pRightHandPos);
            for (int i = 0; i < 16; i++)
            {
                info.AddValue("GES"+i, GetGesture(i));
            }   
        }

        /// <summary>
        /// Setzt die Geste mit entsprechendem Index auf den gewählten Wert.
        /// </summary>
        /// <param name="_index">Index der Geste im Enum</param>
        /// <param name="_value">True oder False</param>
       public void SetGesture(int _index, Boolean _value)
       {
           #region Switch _index:

           switch (_index)
           {
               case 0:
                   this.pRightArmOut = _value;
                   break;
               case 1:
                   this.pRightArmAcross = _value;
                   break;
               case 2:
                   this.pRightArmForward = _value;
                   break;
               case 3:
                   this.pRightArmUp = _value;
                   break;
               case 4:
                   this.pRightHandUp = _value;
                   break;
               case 5:
                   this.pLeftArmOut = _value;
                   break;
               case 6:
                   this.pLeftArmAcross = _value;
                   break;
               case 7:
                   this.pLeftArmForward = _value;
                   break;
               case 8:
                   this.pLeftArmUp = _value;
                   break;
               case 9:
                   this.pLeftHandUp = _value;
                   break;
               case 10:
                   this.pSwipeLeft = _value;
                   break;
               case 11:
                   this.pSwipeRight = _value;
                   break;
               case 12:
                   this.pSwipeUp = _value;
                   break;
               case 13:
                   this.pSwipeDown = _value;
                   break;
               case 14:
                   this.pSwipeUpperLeft = _value;
                   break;
               case 15:
                   this.pSwipeUpperRight = _value;
                   break;
               case 16:
                   this.pSwipeLowerLeft = _value;
                   break;
               case 17:
                   this.pSwipeLowerRight = _value;
                   break;
               default:
                   throw new IndexOutOfRangeException("Wert zwischen 0 und 17 wird erwartet!");
           }

           #endregion
       }

        /// <summary>
        /// Gibt die Belegung der mit dem Index angesprochenen Geste (Boolean) zurück.
        /// </summary>
        /// <param name="_index">Index der Geste im Enum</param>
        /// <returns>Boolean für Belegung des Gesten-Booleans</returns>
       public Boolean GetGesture(int _index)
       {
           #region Switch _index:

           switch (_index)
           {
               case 0:
                   return this.pRightArmOut;
               case 1:
                   return this.pRightArmAcross;
               case 2:
                   return this.pRightArmForward;
               case 3:
                   return this.pRightArmUp;
               case 4:
                   return this.pRightHandUp;
               case 5:
                   return this.pLeftArmOut;
               case 6:
                   return this.pLeftArmAcross;
               case 7:
                   return this.pLeftArmForward;
               case 8:
                   return this.pLeftArmUp;
               case 9:
                   return this.pLeftHandUp;
               case 10:
                   return this.pSwipeLeft;
               case 11:
                   return this.pSwipeRight;
               case 12:
                   return this.pSwipeUp;
               case 13:
                   return this.pSwipeDown;
               case 14:
                   return this.pSwipeUpperLeft;
               case 15:
                   return this.pSwipeUpperRight;
               case 16:
                   return this.pSwipeLowerLeft;
               case 17:
                   return this.pSwipeLowerRight;
               default:
                   throw new IndexOutOfRangeException("Wert zwischen 0 und 17 wird erwartet!");
           }

           #endregion
       }

        #endregion
   }
}
